#include "Vector2.h"
#include "Vector2.h"
#include "Vector3.h"
#include <math.h>
#include "Error.h"

/**


 @author F. Aubert

*/



using namespace prog3d;
using namespace std;


float Vector2::_fc[2];

void Vector2::cnew() {
    this->set(0,0);
}

Vector2::Vector2() {
    cnew();
}

Vector2::Vector2(double x,double y) {
    cnew();
    this->set(x,y);
}

Vector2::Vector2(const Vector2 &a,const Vector2 &b) {
  this->set(b);
  this->sub(a);
}

void Vector2::set(const Vector2 &a,const Vector2 &b) {
  this->set(a);
  this->sub(b);
}


void Vector2::set(double x,double y) {
    _c[0]=x;_c[1]=y;
}

void Vector2::set(const Vector2 &copy) {
    this->set(copy.x(),copy.y());
}

const float *Vector2::fv() const {
    _fc[0]=_c[0];_fc[1]=_c[1];
    return _fc;
}


double Vector2::length2() {
    return _c[0]*_c[0]+_c[1]*_c[1];
}

double Vector2::length() {
    return sqrt(this->length2());
}

void Vector2::normalize() {
    double d=this->length();
    if (fabs(d)<EPSILON_PREC) {
        throw "Normale nulle";
    }
    _c[0]/=d;
    _c[1]/=d;

}


void Vector2::add(const Vector2 &a) {
    this->set(this->x()+a.x(),this->y()+a.y());
}

void Vector2::add(const Vector2 &a,const Vector2 &b) {
    this->set(b.x()+a.x(),
        b.y()+a.y());
}

void Vector2::sub(const Vector2 &a) {
    this->set(this->x()-a.x(),
        this->y()-a.y());
}


void Vector2::sub(const Vector2 &a,const Vector2 &b) {
    this->set(a.x()+b.x(),
        a.y()+b.y());
}

double Vector2::dot(const Vector2 &a) {
    return x()*a.x()+y()*a.y();
}


void Vector2::scale(double k) {
    _c[0]*=k;
    _c[1]*=k;
}



void Vector2::mid(const Vector2& n1,const Vector2 &n2) {
    this->add(n1,n2);
    this->scale(0.5);
}


void Vector2::mid(const Vector2& n1) {
    this->add(n1);
    this->scale(0.5);
}



void Vector2::print() {
    cout << "x=" << this->x() << ",y=" << this->y() << endl;
}

Vector2::~Vector2() {}


//namespace prog3d {
Vector2 prog3d::operator +(const Vector2 &a,const Vector2 &b) {
    Vector2 p(a);
    p.add(b);
    return p;
}

Vector2 prog3d::operator -(const Vector2 &a,const Vector2 &b) {
    Vector2 p(a);
    p.sub(b);
    return p;
}

Vector2 prog3d::operator *(double k,const Vector2 &b) {
    Vector2 p(b);
    p.scale(k);
    return p;
}
//}

Vector2 prog3d::operator *(const Vector2 &b,double k) {
    return k*b;
}

Vector2 &Vector2::operator=(const Vector2 &a) {
    this->set(a);
    return *this;
}


ostream& prog3d::operator <<(std::ostream &s,const Vector2 &q) {
    s << "(" << q.x() << "," << q.y() << ")";
    return s;
}


// donne un vecteur normé orthogonal au segment [this,P2].
Vector2 Vector2::normalSegment(const Vector2 &p2) {
    Vector2 res;
    res.set(this->y()-p2.y(),p2.x()-this->x());
    res.normalize();
    return res;
}

double Vector2::distance2(const Vector2 &a) const {
    Vector2 l;
    l.set(*this,a);
    return l.length2();
}

double Vector2::distance(const Vector2 &a) const {
    Vector2 l;
    l.set(*this,a);
    return l.length();
}




